home *** CD-ROM | disk | FTP | other *** search
/ TPUG - Toronto PET Users Group / TPUG Users Group CD / TPUG Users Group CD.iso / AMIGA / AMICUS / AMICUS05.ADF / IFF / ilbmw.c < prev    next >
C/C++ Source or Header  |  1986-04-20  |  5KB  |  147 lines

  1.  
  2. /*----------------------------------------------------------------------*
  3.  * ILBMW.C  Support routines for writing ILBM files.            1/23/86
  4.  * (IFF is Interchange Format File.)
  5.  *
  6.  * By Jerry Morrison and Steve Shaw, Electronic Arts.
  7.  * This software is in the public domain.
  8.  *
  9.  * This version for the Commodore-Amiga computer.
  10.  *----------------------------------------------------------------------*/
  11. #include "iff/packer.h"
  12. #include "iff/ilbm.h"
  13.  
  14. /*---------- InitBMHdr -------------------------------------------------*/
  15. IFFP InitBMHdr(bmHdr0, bitmap, masking, compression, transparentColor,
  16.          pageWidth, pageHeight)
  17.         BitMapHeader *bmHdr0;  struct BitMap *bitmap;
  18.         WORD masking;         /* Masking */
  19.      WORD compression;   /* Compression */
  20.      WORD transparentColor;   /* UWORD */
  21.      WORD pageWidth, pageHeight;
  22.     {
  23.     register BitMapHeader *bmHdr = bmHdr0;
  24.     register WORD rowBytes = bitmap->BytesPerRow;
  25.  
  26.     bmHdr->w = rowBytes << 3;
  27.     bmHdr->h = bitmap->Rows;
  28.     bmHdr->x = bmHdr->y = 0;  /* Default position is (0,0).*/
  29.     bmHdr->nPlanes = bitmap->Depth;
  30.     bmHdr->masking = masking;
  31.     bmHdr->compression = compression;
  32.     bmHdr->pad1 = 0;
  33.     bmHdr->transparentColor = transparentColor;
  34.     bmHdr->xAspect = bmHdr->yAspect = 1;
  35.     bmHdr->pageWidth = pageWidth;
  36.     bmHdr->pageHeight = pageHeight;
  37.  
  38.     if (pageWidth = 320)
  39.      switch (pageHeight) {
  40.          case 200: {bmHdr->xAspect = x320x200Aspect;
  41.                  bmHdr->yAspect = y320x200Aspect; break;}
  42.          case 400: {bmHdr->xAspect = x320x400Aspect;
  43.                  bmHdr->yAspect = y320x400Aspect; break;}
  44.          }
  45.     else if (pageWidth = 640)
  46.      switch (pageHeight) {
  47.          case 200: {bmHdr->xAspect = x640x200Aspect;
  48.                  bmHdr->yAspect = y640x200Aspect; break;}
  49.          case 400: {bmHdr->xAspect = x640x400Aspect;
  50.                  bmHdr->yAspect = y640x400Aspect; break;}
  51.          }
  52.  
  53.     return( IS_ODD(rowBytes) ? CLIENT_ERROR : IFF_OKAY );
  54.     }
  55.  
  56. /*---------- PutCMAP ---------------------------------------------------*/
  57. IFFP PutCMAP(context, colorMap, depth)   
  58.       GroupContext *context;  WORD *colorMap;  UBYTE depth;
  59.    {
  60.    register LONG nColorRegs;   
  61.    IFFP iffp;
  62.    ColorRegister colorReg;
  63.  
  64.    if (depth > MaxAmDepth)   depth = MaxAmDepth;
  65.    nColorRegs = 1 << depth;
  66.  
  67.    iffp = PutCkHdr(context, ID_CMAP, nColorRegs * sizeofColorRegister);
  68.    CheckIFFP();
  69.  
  70.    for ( ;  nColorRegs;  --nColorRegs)  {
  71.       colorReg.red   = ( *colorMap >> 4 ) & 0xf0;
  72.       colorReg.green = ( *colorMap      ) & 0xf0;
  73.       colorReg.blue  = ( *colorMap << 4 ) & 0xf0;
  74.       iffp = IFFWriteBytes(context, (BYTE *)&colorReg, sizeofColorRegister);
  75.       CheckIFFP();
  76.       ++colorMap;
  77.       }
  78.  
  79.    iffp = PutCkEnd(context);
  80.    return(iffp);
  81.    }
  82.  
  83. /*---------- PutBODY ---------------------------------------------------*/
  84. /* NOTE: This implementation could be a LOT faster if it used more of the
  85.  * supplied buffer. It would make far fewer calls to IFFWriteBytes (and
  86.  * therefore to DOS Write). */
  87. IFFP PutBODY(context, bitmap, mask, bmHdr, buffer, bufsize)
  88.       GroupContext *context;  struct BitMap *bitmap;  BYTE *mask;
  89.       BitMapHeader *bmHdr;  BYTE *buffer;  LONG bufsize;
  90.    {         
  91.    IFFP iffp;
  92.    LONG rowBytes = bitmap->BytesPerRow;
  93.    int dstDepth = bmHdr->nPlanes;
  94.    Compression compression = bmHdr->compression;
  95.    int planeCnt;         /* number of bit planes including mask */
  96.    register int iPlane, iRow;
  97.    register LONG packedRowBytes;
  98.    BYTE *buf;
  99.    BYTE *planes[MaxAmDepth + 1]; /* array of ptrs to planes & mask */
  100.  
  101.    if ( bufsize < MaxPackedSize(rowBytes)  ||     /* Must buffer a comprsd row*/
  102.         compression > cmpByteRun1  ||        /* bad arg */
  103.      bitmap->Rows != bmHdr->h   ||      /* inconsistent */
  104.      rowBytes != RowBytes(bmHdr->w)  || /* inconsistent*/
  105.      bitmap->Depth < dstDepth   ||      /* inconsistent */
  106.      dstDepth > MaxAmDepth )            /* too many for this routine*/
  107.       return(CLIENT_ERROR);
  108.  
  109.    planeCnt = dstDepth + (mask == NULL ? 0 : 1);
  110.  
  111.    /* Copy the ptrs to bit & mask planes into local array "planes" */
  112.    for (iPlane = 0; iPlane < dstDepth; iPlane++)
  113.       planes[iPlane] = (BYTE *)bitmap->Planes[iPlane];
  114.    if (mask != NULL)
  115.       planes[dstDepth] = mask;
  116.  
  117.    /* Write out a BODY chunk header */
  118.    iffp = PutCkHdr(context, ID_BODY, szNotYetKnown);
  119.    CheckIFFP();
  120.  
  121.    /* Write out the BODY contents */
  122.    for (iRow = bmHdr->h; iRow > 0; iRow--)  {
  123.       for (iPlane = 0; iPlane < planeCnt; iPlane++)  {
  124.  
  125.          /* Write next row.*/
  126.          if (compression == cmpNone) {
  127.             iffp = IFFWriteBytes(context, planes[iPlane], rowBytes);
  128.             planes[iPlane] += rowBytes;
  129.             }
  130.  
  131.          /* Compress and write next row.*/
  132.          else {
  133.             buf = buffer;
  134.             packedRowBytes = PackRow(&planes[iPlane], &buf, rowBytes);
  135.             iffp = IFFWriteBytes(context, buffer, packedRowBytes);
  136.             }
  137.  
  138.          CheckIFFP();
  139.          }
  140.       }
  141.  
  142.    /* Finish the chunk */
  143.    iffp = PutCkEnd(context);
  144.    return(iffp);
  145.    }
  146.  
  147.